/**
*
*RT-Thread的mailbox组件在Linux下通过pthread和信号量来模拟实现。
*
**/

#include "message_mailbox.h"

static inline void dump_queue(mailbox_t *mb)
{
    printf("r_index=%d, w_index=%d -->[", mb->read_index, mb->write_index);
    for(int i = 0; i < mb->capacity; i++)
    {
        printf("%d ", mb->buffer[i]);
    }
    printf("]\n");
}

// 初始化 mailbox
mb_err_t mb_init(mailbox_t *mb, int32_t capacity)
{
    mb->read_index = mb->write_index = 0;

    mb->buffer = (uint32_t *)malloc(sizeof(uint32_t) * capacity);
    if (mb->buffer == NULL)
    {
        printf("Failed to allocate memory for mailbox buffer.\n");
        return MB_ENOMEM;
    }
    memset(mb->buffer, 0, sizeof(uint32_t) * capacity);

    sem_init(&mb->blank_sem, 0, capacity); // initial blank_sem is ring_queue capacity.
    sem_init(&mb->data_sem, 0, 0);
}

// 销毁 mailbox
mb_err_t mb_destroy(mailbox_t *mb)
{
    sem_destroy(&mb->blank_sem);
    sem_destroy(&mb->data_sem);

    free(mb->buffer);
    mb->buffer = NULL;

    return MB_EOK;
}

// 向 mailbox 发送数据
mb_err_t mb_send_wait(mailbox_t *mb, uint32_t value)
{
    sem_wait(&mb->blank_sem);

    pthread_mutex_lock(&mb->producer_lock); // 加锁，保证生产者之间有序操作
    mb->buffer[mb->write_index] = value;
    mb->write_index++;
    mb->write_index = mb->write_index % mb->capacity;
    pthread_mutex_unlock(&mb->producer_lock);

    sem_post(&mb->data_sem); // 发送成功，通知读线程

    return MB_EOK;
}
 
// 从 mailbox 接收数据
mb_err_t mb_recv_wait(mailbox_t *mb, uint32_t *value) 
{
    sem_wait(&mb->data_sem);

    pthread_mutex_lock(&mb->consumer_lock); // 加锁，保证消费者之间有序操作
    *value = mb->buffer[mb->read_index];
    mb->read_index++;
    mb->read_index = mb->read_index % mb->capacity;
    pthread_mutex_unlock(&mb->consumer_lock);

    sem_post(&mb->blank_sem); // 接收成功，通知写线程

    return MB_EOK;
}
